﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using InterfazGrafico.LibreriaClases.Clases;
using InterfazGrafico.LibreriaConstantes;
using InterfazGrafico.LibreriaConstantes.Elementos;

namespace InterfazGrafico.LibreriaClases.Propiedades
{
    /// <summary>
    /// Almacena las propiedades de un elemento específico.
    /// </summary>
    public class PAnalizarDatos : Propiedades
    {
        /// <summary>
        /// Entrada de datos.
        /// </summary>
        public string Entrada
        {
            get
            {
                return this.getPropiedadString(CAnalizarDatos.Entrada);
            }
            set
            {
                this.setOrAddPropiedad(CAnalizarDatos.Entrada, value);
            }
        }

        /// <summary>
        /// Salida de datos.
        /// </summary>
        public string Salida
        {
            get
            {
                return this.getPropiedadString(CAnalizarDatos.Salida);
            }
            set
            {
                this.setOrAddPropiedad(CAnalizarDatos.Salida, value);
            }
        }

        /// <summary>
        /// Estructura de entrada.
        /// </summary>
        public string EstructuraEntrada
        {
            get
            {
                return this.getPropiedadString(CAnalizarDatos.EstructuraEntrada);
            }
            set
            {
                this.setOrAddPropiedad(CAnalizarDatos.EstructuraEntrada, value);
            }
        }

        /// <summary>
        /// Estructura de salida.
        /// </summary>
        public string EstructuraSalida
        {
            get
            {
                return this.getPropiedadString(CAnalizarDatos.EstructuraSalida);
            }
            set
            {
                this.setOrAddPropiedad(CAnalizarDatos.EstructuraSalida, value);
            }
        }

        /// <summary>
        /// Salida de datos con palabras no encontradas.
        /// </summary>
        public string SalidaPalabrasNoEncontradas
        {
            get
            {
                return this.getPropiedadString(CAnalizarDatos.SalidaPalabrasNoEncontradas);
            }
            set
            {
                this.setOrAddPropiedad(CAnalizarDatos.SalidaPalabrasNoEncontradas, value);
            }
        }

        /// <summary>
        /// Salida de datos con patrones no encontrados.
        /// </summary>
        public string SalidaPatronesNoEncontrados
        {
            get
            {
                return this.getPropiedadString(CAnalizarDatos.SalidaPatronesNoEncontrados);
            }
            set
            {
                this.setOrAddPropiedad(CAnalizarDatos.SalidaPatronesNoEncontrados, value);
            }
        }

        /// <summary>
        /// Diccionario de alias asociados a los campos.
        /// </summary>
        public Dictionary<string, string> DiccionarioAliasCampos
        {
            get
            {
                return this.getPropiedadDiccionarioStringString(CAnalizarDatos.DiccionarioAliasCampos);
            }
            set
            {
                this.setOrAddPropiedad(CAnalizarDatos.DiccionarioAliasCampos, value);
            }
        }

        /// <summary>
        /// Lista de campos a analizar.
        /// </summary>
        public List<string> ListaCamposAnalizar
        {
            get
            {
                return this.getPropiedadListaString(CAnalizarDatos.ListaCamposAnalizar);
            }
            set
            {
                this.setOrAddPropiedad(CAnalizarDatos.ListaCamposAnalizar, value);
            }
        }

        /// <summary>
        /// Lista de caracteres separadores.
        /// </summary>
        public List<char> ListaSeparadores
        {
            get
            {
                return this.getPropiedadListaChar(CAnalizarDatos.ListaSeparadores);
            }
            set
            {
                this.setOrAddPropiedad(CAnalizarDatos.ListaSeparadores, value);
            }
        }

        /// <summary>
        /// Lista de caracteres especiales.
        /// </summary>
        public List<char> ListaCaracteresEspeciales
        {
            get
            {
                return this.getPropiedadListaChar(CAnalizarDatos.ListaEspeciales);
            }
            set
            {
                this.setOrAddPropiedad(CAnalizarDatos.ListaEspeciales, value);
            }
        }

        /// <summary>
        /// Lista de datos a eliminar.
        /// </summary>
        public List<string> ListaDatosEliminar
        {
            get
            {
                return this.getPropiedadListaString(CAnalizarDatos.ListaDatosEliminar);
            }
            set
            {
                this.setOrAddPropiedad(CAnalizarDatos.ListaDatosEliminar, value);
            }
        }

        /// <summary>
        /// Diccionario de datos a modificar.
        /// </summary>
        public Dictionary<string, string> DiccionarioDatosModificar
        {
            get
            {
                return this.getPropiedadDiccionarioStringString(CAnalizarDatos.DiccionarioDatosModificar);
            }
            set
            {
                this.setOrAddPropiedad(CAnalizarDatos.DiccionarioDatosModificar, value);
            }
        }

        /// <summary>
        /// Fichero definición de datos.
        /// </summary>
        public string DefinicionDatos
        {
            get
            {
                return this.getPropiedadString(CAnalizarDatos.DefinicionDatos);
            }
            set
            {
                this.setOrAddPropiedad(CAnalizarDatos.DefinicionDatos, value);
            }
        }

        /// <summary>
        /// Fichero definición de registros.
        /// </summary>
        public string DefinicionRegistros
        {
            get
            {
                return this.getPropiedadString(CAnalizarDatos.DefinicionRegistros);
            }
            set
            {
                this.setOrAddPropiedad(CAnalizarDatos.DefinicionRegistros, value);
            }
        }

        /// <summary>
        /// Constructor por defecto.
        /// </summary>
        public PAnalizarDatos()
            : base()
        {
        }

        /// <summary>
        /// Obtiene los parámetros a partir del fichero XML indicado.
        /// </summary>
        /// <param name="fichero">Fichero de configuración XML</param>
        override public void leer(string fichero)
        {
            try
            {
                base.leer(fichero);
                XmlDocument xml = LeerXml.AbrirFicheroParametros(fichero);

                try
                { this.Entrada = LeerXml.ObtenerValorCampo(xml, CAnalizarDatos.RutaEntrada); }
                catch (Exception)
                { this.Entrada = string.Empty; }

                try
                { this.Salida = LeerXml.ObtenerValorCampo(xml, CAnalizarDatos.RutaSalida); }
                catch (Exception)
                { this.Salida = string.Empty; }

                try
                { this.EstructuraEntrada = LeerXml.ObtenerValorCampo(xml, CAnalizarDatos.RutaEstructuraEntrada); }
                catch (Exception)
                { this.EstructuraEntrada = string.Empty; }

                try
                { this.EstructuraSalida = LeerXml.ObtenerValorCampo(xml, CAnalizarDatos.RutaEstructuraSalida); }
                catch (Exception)
                { this.EstructuraSalida = string.Empty; }

                // Configuracion
                try
                { this.SalidaPalabrasNoEncontradas = LeerXml.ObtenerValorCampo(xml, CAnalizarDatos.RutaSalidaPalabras); }
                catch (Exception)
                { this.SalidaPalabrasNoEncontradas = string.Empty; }
                try
                { this.SalidaPatronesNoEncontrados = LeerXml.ObtenerValorCampo(xml, CAnalizarDatos.RutaSalidaPatrones); }
                catch (Exception)
                { this.SalidaPatronesNoEncontrados = string.Empty; }

                // Alias
                try
                { 
                    int numeroAlias = LeerXml.ObtenerNumeroNodosCampo(xml, CAnalizarDatos.RutaListaAlias);
                    this.DiccionarioAliasCampos = new Dictionary<string,string>();
                    for (int indiceAlias = 0; indiceAlias < numeroAlias; indiceAlias++)
                    {
                        string alias = LeerXml.ObtenerValorCampo(xml, CAnalizarDatos.RutaListaAlias, indiceAlias, CAnalizarDatos.NodoListaAliasAliasNombre);
                        string campo = LeerXml.ObtenerValorCampo(xml, CAnalizarDatos.RutaListaAlias, indiceAlias, CAnalizarDatos.NodoListaAliasAliasCampo);
                        this.DiccionarioAliasCampos.Add(alias, campo);
                    }
                }
                catch (Exception)
                {
                    this.DiccionarioAliasCampos = new Dictionary<string,string>();
                }

                // Campos a analizar
                try
                { 
                    int numeroCampos = LeerXml.ObtenerNumeroNodosCampo(xml, CAnalizarDatos.RutaCamposAnalizar);
                    this.ListaCamposAnalizar = new List<string>();
                    for (int indiceCampo = 0; indiceCampo < numeroCampos; indiceCampo++)
                    {
                        string campo = LeerXml.ObtenerValorCampo(xml, CAnalizarDatos.RutaCamposAnalizar, indiceCampo);
                        this.ListaCamposAnalizar.Add(campo);
                    }
                }
                catch (Exception)
                {
                    this.ListaCamposAnalizar = new List<string>();
                }

                // Separadores
                try
                { 
                    int numeroSeparadores = LeerXml.ObtenerNumeroNodosCampo(xml, CAnalizarDatos.RutaSeparadores);
                    this.ListaSeparadores = new List<char>();
                    for (int indiceSeparador = 0; indiceSeparador < numeroSeparadores; indiceSeparador++)
                    {
                        string separador = LeerXml.ObtenerValorCampo(xml, CAnalizarDatos.RutaSeparadores, indiceSeparador);
                        char sep = separador[0];
                        if (separador.Length > 1 && "\\t".Equals(separador))
                            sep = '\t';
                        this.ListaSeparadores.Add(sep);
                    }
                }
                catch (Exception)
                {
                    this.ListaSeparadores = new List<char>();
                }

                // Caracteres especiales
                try
                {
                    int numeroCaracteres = LeerXml.ObtenerNumeroNodosCampo(xml, CAnalizarDatos.RutaCaracteresEspeciales);
                    this.ListaCaracteresEspeciales = new List<char>();
                    for (int indiceCaracter = 0; indiceCaracter < numeroCaracteres; indiceCaracter++)
                    {
                        string caracter = LeerXml.ObtenerValorCampo(xml, CAnalizarDatos.RutaCaracteresEspeciales, indiceCaracter);
                        char car = caracter[0];
                        if (caracter.Length > 1 && "\\t".Equals(caracter))
                            car = '\t';
                        this.ListaCaracteresEspeciales.Add(car);
                    }
                }
                catch (Exception)
                {
                    this.ListaCaracteresEspeciales = new List<char>();
                }

                // Datos a eliminar
                try
                { 
                    int numeroDatos = LeerXml.ObtenerNumeroNodosCampo(xml, CAnalizarDatos.RutaListaEliminar);
                    this.ListaDatosEliminar = new List<string>();
                    for (int indiceDato = 0; indiceDato < numeroDatos; indiceDato++)
                    {
                        string dato = LeerXml.ObtenerValorCampo(xml, CAnalizarDatos.RutaListaEliminar, indiceDato);
                        this.ListaDatosEliminar.Add(dato);
                    }
                }
                catch (Exception)
                {
                    this.ListaDatosEliminar = new List<string>();
                }

                // Datos a modificar
                try
                {
                    int numeroDatos = LeerXml.ObtenerNumeroNodosCampo(xml, CAnalizarDatos.RutaListaModificar);
                    this.DiccionarioDatosModificar = new Dictionary<string,string>();
                    for (int indiceDato = 0; indiceDato < numeroDatos; indiceDato++)
                    {
                        string original = LeerXml.ObtenerValorCampo(xml, CAnalizarDatos.RutaListaModificar, indiceDato, CAnalizarDatos.NodoListaModificarModificacionOriginal);
                        string nuevo = LeerXml.ObtenerValorCampo(xml, CAnalizarDatos.RutaListaModificar, indiceDato, CAnalizarDatos.NodoListaModificarModificacionNuevo);
                        this.DiccionarioDatosModificar.Add(original, nuevo);
                    }
                }
                catch (Exception)
                {
                    this.DiccionarioDatosModificar = new Dictionary<string,string>();
                }

                // Definicion de Datos
                try
                { this.DefinicionDatos = LeerXml.ObtenerValorCampo(xml, CAnalizarDatos.RutaDefinicionDatos); }
                catch (Exception)
                { this.EstructuraSalida = string.Empty; }

                // Definicion de Registros
                try
                { this.DefinicionRegistros = LeerXml.ObtenerValorCampo(xml, CAnalizarDatos.RutaDefinicionRegistros); }
                catch (Exception)
                { this.EstructuraSalida = string.Empty; }
            }
            catch (Exception ex)
            {
                throw new ApplicationException(Constantes.ERROR_LECTURA_FICHERO_CONFIGURACION, ex);
            }
        }

        /// <summary>
        /// Escribe los parámetros al fichero XML indicado.
        /// </summary>
        /// <param name="fichero">Fichero de configuración XML</param>
        public override void escribir(string fichero)
        {
            try
            {
                base.escribir(fichero);
                XmlWriter xml = EscribirXml.AbrirFicheroParametros(fichero);
                EscribirXml.InicioElemento(xml, CAnalizarDatos.NodoRaiz);
                EscribirXml.EscribeNodo(xml, CAnalizarDatos.NodoEntrada, Entrada);
                EscribirXml.EscribeNodo(xml, CAnalizarDatos.NodoSalida, Salida);
                EscribirXml.EscribeNodo(xml, CAnalizarDatos.NodoEstructuraEntrada, EstructuraEntrada);
                EscribirXml.EscribeNodo(xml, CAnalizarDatos.NodoEstructuraSalida, EstructuraSalida);
                
                // Configuración
                EscribirXml.InicioElemento(xml, CAnalizarDatos.NodoConfiguracion);
                
                // Salidas datos no encontrados
                EscribirXml.EscribeNodo(xml, CAnalizarDatos.NodoSalidaPalabrasNoEncontradas, SalidaPalabrasNoEncontradas);
                EscribirXml.EscribeNodo(xml, CAnalizarDatos.NodoSalidaPatronesNoEncontrados, SalidaPatronesNoEncontrados);

                // Alias
                EscribirXml.InicioElemento(xml, CAnalizarDatos.NodoListaAlias);
                foreach (string alias in DiccionarioAliasCampos.Keys)
                {
                    EscribirXml.InicioElemento(xml, CAnalizarDatos.NodoListaAliasAlias);
                    EscribirXml.EscribeNodo(xml, CAnalizarDatos.NodoListaAliasAliasNombre, alias);
                    EscribirXml.EscribeNodo(xml, CAnalizarDatos.NodoListaAliasAliasCampo, DiccionarioAliasCampos[alias]);
                    EscribirXml.FinElemento(xml);
                }
                EscribirXml.FinElemento(xml);

                // Campos a analizar
                EscribirXml.InicioElemento(xml, CAnalizarDatos.NodoCamposAnalizar);
                foreach (string campo in ListaCamposAnalizar)
                    EscribirXml.EscribeNodo(xml, CAnalizarDatos.NodoCamposAnalizarCampo, campo);
                EscribirXml.FinElemento(xml);

                // Separadores
                EscribirXml.InicioElemento(xml, CAnalizarDatos.NodoSeparadores);
                foreach (char separador in ListaSeparadores)
                {
                    if ('\t'.Equals(separador))
                        EscribirXml.EscribeNodo(xml, CAnalizarDatos.NodoSeparadoresSeparador, "\\t");
                    else
                        EscribirXml.EscribeNodo(xml, CAnalizarDatos.NodoSeparadoresSeparador, separador.ToString());
                }
                EscribirXml.FinElemento(xml);

                // Caracteres especiales
                EscribirXml.InicioElemento(xml, CAnalizarDatos.NodoCaracteresEspeciales);
                foreach (char caracter in ListaCaracteresEspeciales)
                {
                    if ('\t'.Equals(caracter))
                        EscribirXml.EscribeNodo(xml, CAnalizarDatos.NodoCaracteresEspecialesCaracter, "\\t");
                    else
                        EscribirXml.EscribeNodo(xml, CAnalizarDatos.NodoCaracteresEspecialesCaracter, caracter.ToString());
                }
                EscribirXml.FinElemento(xml);
                
                // Datos a eliminar
                EscribirXml.InicioElemento(xml, CAnalizarDatos.NodoListaEliminar);
                foreach (string dato in ListaDatosEliminar)
                    EscribirXml.EscribeNodo(xml, CAnalizarDatos.NodoListaEliminarValor, dato);
                EscribirXml.FinElemento(xml);

                // Datos a modificar
                EscribirXml.InicioElemento(xml, CAnalizarDatos.NodoListaModificar);
                foreach (string dato in DiccionarioDatosModificar.Keys)
                {
                    EscribirXml.InicioElemento(xml, CAnalizarDatos.NodoListaModificarModificacion);
                    EscribirXml.EscribeNodo(xml, CAnalizarDatos.NodoListaModificarModificacionOriginal, dato);
                    EscribirXml.EscribeNodo(xml, CAnalizarDatos.NodoListaModificarModificacionNuevo, DiccionarioDatosModificar[dato]);
                    EscribirXml.FinElemento(xml);
                }
                EscribirXml.FinElemento(xml);

                // Definición de datos
                EscribirXml.EscribeNodo(xml, CAnalizarDatos.NodoDefinicionDatos, DefinicionDatos);
                // Definición de registros
                EscribirXml.EscribeNodo(xml, CAnalizarDatos.NodoDefinicionRegistros, DefinicionRegistros);

                EscribirXml.FinElemento(xml);
                EscribirXml.FinElemento(xml);
                EscribirXml.Flush(xml);
                EscribirXml.Close(xml);
            }
            catch (Exception ex)
            {
                throw new ApplicationException(Constantes.ERROR_ESCRITURA_FICHERO_CONFIGURACION, ex);
            }
        }
    }
}
 